#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
using namespace std;

//继承
//作用：减少重复代码
//语法：  class 子类: 继承方式 父类
//子类又叫派生类， 父类又叫基类

class class01			//父类
{
public:
	void Grade()
	{
		cout << "年级: 2022级" << endl;
	}
	void Class()
	{
		cout << "班级: 01班" << endl;
	}
	void Teacher()
	{
		cout << "班主任: 林老师" << endl;
	}
};

class Student : public class01		//子类，子类可以调用父类的属性
{
public:
	void Name(string name)
	{
		cout << "姓名: " << name << endl;
	}
};

void test01(string name)
{
	Student stu1;
	stu1.Name(name);
	stu1.Grade();
	stu1.Class();
	stu1.Teacher();
	cout << endl;
}

int main()
{
	test01("小明");

	test01("小红");

	return 0;
}





//继承方式
//继承语法：  class 子类: 继承方式 父类
//继承方式有：公共继承(public)，保护继承(protected)，私有继承(private)
/*
	父类中private权限的属性，无论什么继承子类都无法访问
	公共继承：父类中的属性在子类中有相同的权限
	保护继承：父类中的属性在子类中全为保护权限(protected)
	私有继承：父类中的属性在子类中全为私有权限(private)
*/

//公共继承
class Base1
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;
};

class Son : public Base1
{
public:
	void func()
	{
		m_A = 10;
		m_B = 20;
		//m_C = 10; //父类中的私有权限无法访问
	}
};
void test01()
{
	Son s1;
	s1.m_A = 100;
	//s1.m_B;	//m_B在s1中是保护权限，类外无法访问
}

//保护继承
class Son2 : protected Base1
{
public:
	void func()
	{
		m_A = 10;	//父类中其余权限变为保护权限
		m_B = 20;
		//m_C = 10; //父类中的私有权限无法访问
	}
};

void test02()
{
	Son2 s2;
	//s2.m_A;  //Sonw中 m_A变为保护权限，类外无法访问
}

//私有继承类似





//继承中的对象模型
//父类中所有非静态成员属性都会被子类继承
//父类中私有成员属性被编译器隐藏了，无法访问，但是继承了

class Base
{
public:
	int m_A;
protected:
	int m_B;
private:
	int m_C;

};

class Son : public Base
{
public:
	int m_D;
};

void test01()
{
	cout << "size of Son = " << sizeof(Son) << endl;
}

int main()
{
	test01();
	return 0;
}

//利用工具查看类的成员
/*
	1.找到 VS开发人员命令提示符(Cross Tools Commad...)
	2.切换盘符和文件位置
	3.输入:cl /d1 reportSingleClassLayout类名 所属文件名
*/



//继承中的构造和析构顺序:
//先构造父类，再构造子类，结束时，先析构子类，再析构父类



//继承同名成员处理方式
//当子类与父类出现同名(参数可以不同)的成员时，直接访问就是访问的子类成员
//若想访问父类成员，加上作用域即可,

class Base
{
public:
	void func(int a)
	{
		cout << "访问父类成员。" << endl;
	}
};

class Son : public Base
{
public:
	void func()
	{
		cout << "访问子类成员。" << endl;
	}
};

void test01()
{
	Son s1;
	s1.func();
	s1.Base::func(12);
}

int main()
{
	test01();
	return 0;
}




//继承中的同名静态成员处理方式(与非静态成员类似)
//访问子类同名(参数可以不同)成员：直接访问
//访问父类同名(参数可以不同)成员：加作用域

class Base
{
public:
	static int m_A;

	static void func()
	{
		cout << "Base_static void func()" << endl;
	}

};
int Base::m_A = 100;	//静态成员变量类内定义，内外初始化

class Son : public Base
{
public:
	static int m_A;

	static void func()
	{
		cout << "Son_static void func()" << endl;
	}
};
int Son::m_A = 200;

void test01()
{
	Son s;
	//通过对象访问
	cout << "通过对象访问" << endl;
	cout << "son_m_A = " << s.m_A << endl;
	cout << "base_m_A = " << s.Base::m_A << endl;

	//通过类名访问
	cout << "通过类名访问" << endl;
	cout << "son_m_A = " << Son::m_A << endl;
	cout << "base_m_A = " << Base::m_A << endl;
	cout << "base_m_A = " << Son::Base::m_A << endl;
	//第一个::表示通过类名方式访问，第二个::表示访问Base作用域下
}

void test02()
{
	Son s;
	//通过对象访问
	cout << "通过对象访问" << endl;
	s.func();
	s.Base::func();

	//通过类名访问
	cout << "通过类名访问" << endl;
	Son::func();
	Base::func();
	Son::Base::func();

}

int main()
{
	//test01();
	test02();
	return 0;
}




//多继承语法
/*
语法： 
class 子类 : 继承方式 父类1, 继承方式 父类2...
多继承可能会引发父类中有同名成员出现，需要加作用域区分
所以c++实际开发中不建议使用多继承
*/

class Base1
{
public:
	Base1()
	{
		m_A = 100;
	}
	void func()
	{
		cout << "Base1_void func()" << endl;
	}

	int m_A;
};

class Base2
{
public:
	Base2()
	{
		m_B = 200;
	}

	void func()
	{
		cout << "Base2_void func()" << endl;
	}

	int m_B;
};

class Son : public Base1, public Base2
{

};

void test01()
{
	Son s1;
	cout << "size of s1 = " << sizeof(s1) << endl;
	cout << "s1.m_A = " << s1.m_A << endl;
	cout << "s1.m_B = " << s1.m_B << endl;
	s1.Base1::func();
	s1.Base2::func();
}

int main()
{
	test01();
	return 0;
}





//菱形继承（钻石继承）
//有两个派生类继承同一个基类，又有一子个类继承了那两个派生类，形成菱形
//钻石继承后，子类继承了两次基类的属性，出现问题

class Animal
{
public:
	int A ;
};
//利用虚继承 解决菱形继承的问题(在:后加virtual)
//Animal类 成为 虚基类
class Sheep :virtual public Animal
{
	int B;
};

class Tuo :virtual public Animal
{
	int C;
};

class YangTuo : public Tuo, public Sheep
{
	int D;
};

void test01()
{
	int x;
	Animal a;
	Sheep s;
	Tuo t;
	YangTuo yt;
	yt.Sheep::A = 18;
	yt.Tuo::A = 28;
	//菱形继承两个父类拥有相同的数据，需要加作用域
	cout << "yt.Sheep::m_Age = " << yt.Sheep::A << endl;
	cout << "yt.Tuo::m_Age = " << yt.Tuo::A << endl;
	//采用虚继承后两个都是28，否则一个为18一个为28
	//虚继承后不用加作用域也能正常输出，不会报错

	//虚继承子类数据成员大小包括:父类数据成员，子类数据成员，虚指针
	cout << sizeof(Animal) << endl;		//一个int
	cout << sizeof(Sheep) << endl;		//
	cout << sizeof(Tuo) << endl;		//
	cout << sizeof(YangTuo) << endl;		//

}
//虚继承并继承的是指针，称为虚基类指针，指向虚基类表
//表中记载偏移量， 通过偏移量找到基类的成员
int main()
{
	test01();

	return 0;
}






//多态
/*
静态多态: 函数重载，运算符重载
动态多态: 派生类和虚函数实现运行时多态
*/

class Animal
{
public:
	virtual void speak()	//加上关键字virtual 变虚函数
	{
		cout << "动物说话" << endl;
	}
	//本质是一个虚函数(表)指针，指向虚函数表
	//表内记录虚函数地址，如 &Animal::speak()
};

class Cat : public Animal
{
public:
	void speak()
	{
		cout << "喵喵喵" << endl;
	}
};
//当子类重写父类虚函数，子类中的虚函数表内部会替换成子类的虚函数地址
//如 &Cat::speak(),父类没有发生改变

class Dog : public Animal
{
public:
	void speak()
	{
		cout << "汪汪汪" << endl;
	}
};

//地址早绑定，在编译阶段确定函数地址
//若想执行猫说话，这个函数地址不能提前绑定
//需要在运行阶段进行绑定，即地址晚绑定，构造虚函数
void Dospeak(Animal& animal)	// Animal& animal = cat;
{
	//父类指针或引用指向子类对象时，发生多态
	animal.speak();
}

void test01()
{
	Cat cat;	// Animal& animal = Cat;  从Cat虚函数表访问Cat::speak()
	Dog dog;	// Animal& animal = Dog; 
	Animal animal;
	Dospeak(cat);
	Dospeak(dog);
	Dospeak(animal);
}

void test02()
{
	//只有成员变量才属于类，但此处是虚函数
	cout << "size of Animal = " << sizeof(Animal) << endl;
}

int main()
{
	//test01();
	test02();
	return 0;
}
//动态多态满足条件
//1.有继承关系
//2.子类要重写父类虚函数(重写需返回类型，函数名，参数完全一样，virtual可加可不加)

//动态多态使用
//父类的指针或引用指向子类对象

//多态优点
//1.代码组织结构清晰
//2.可读性强
//3。利于前期和后期的扩展以及维护




//多态案例———计算器类

//普通写法

class Calculator
{
public:
	int getResult(string s)
	{
		if (s == "+")
			return m_Num1 + m_Num2;
		else if (s == "-")
			return m_Num1 - m_Num2;
		else if (s == "*")
			return m_Num1 * m_Num2;
		else if (s == "/")
			return m_Num1 / m_Num2;
		//若想扩展新的功能，需要修改源码
		//真实开发中，提倡开闭原则
		//对扩展进行开放，对修改进行关闭
	}

	int m_Num1;
	int m_Num2;
};

void test01()
{
	Calculator c;
	c.m_Num1 = 10;
	c.m_Num2 = 5;

	cout << c.m_Num1 << " + " << c.m_Num2 << " = " << c.getResult("+") << endl;
	cout << c.m_Num1 << " - " << c.m_Num2 << " = " << c.getResult("-") << endl;
	cout << c.m_Num1 << " * " << c.m_Num2 << " = " << c.getResult("*") << endl;
	cout << c.m_Num1 << " / " << c.m_Num2 << " = " << c.getResult("/") << endl;
}

int main()
{
	test01();

	return 0;
}


//多态案例

//实现计算器抽象类
class AbstractCalculator
{
public:
	virtual int getResult()
	{
		return 0;
	}

	int m_Num1;
	int m_Num2;
};

class Add : public AbstractCalculator
{
public:
	int getResult()
	{
		return m_Num1 + m_Num2;
	}
};

class Subtraction : public AbstractCalculator
{
public:
	int getResult()
	{
		return m_Num1 - m_Num2;
	}
};

class Multiplication : public AbstractCalculator
{
public:
	int getResult()
	{
		return m_Num1 * m_Num2;
	}
};

class Divide : public AbstractCalculator
{
public:
	int getResult()
	{
		return m_Num1 / m_Num2;
	}
};

int GetResult(AbstractCalculator& abs)
{
	return abs.getResult();
}

//父类引用指向子类对象
void test02()
{
	Add add;
	add.m_Num1 = 10;
	add.m_Num2 = 5;
	cout << add.m_Num1 << " + " << add.m_Num2 << " = " << GetResult(add) << endl;
	
}

//父类指针指向子类对象
void test03()
{
	AbstractCalculator* abc = new Add;
	abc->m_Num1 = 10;
	abc->m_Num2 = 20;

	cout << abc->m_Num1 << " + " << abc->m_Num2 << " = " << abc->getResult() << endl;
	//堆区创建后记得手动销毁
	delete abc;
}

int main()
{
	test02();
	//test03();
	return 0;
}




//纯虚函数和抽象类
//多态中父类的虚函数基本没用， 因此可以把虚函数改为纯虚函数
//类中有了纯虚函数，这个类也称为抽象类
//语法：virtual 返回值类型 函数名 (参数列表) = 0;

//抽象类
//1.无法实例化对象(即不能创建对象)
//2.子类必须重写抽象类中的纯虚函数，否则也属于抽象类

class Base
{
public:
	virtual void func() = 0;
};

class Son : public Base
{
public:
	void func()
	{
		cout << "你好。" << endl;
	}
};

void Keyfun(Base& base)
{
	base.func();
}

void test01()
{
	Son s1;
	Keyfun(s1);
}

void test02()
{
	Base* base = new Son;
	base->func();
	delete base;
}

int main()
{
	test01();
	test02();
	return 0;
}



//多态案例二——制作饮品

class AbstractDrinking
{
public:	
	virtual void Boil() = 0;

	virtual void Brew() = 0;

	virtual void PourInCup() = 0;

	virtual void PutSomething() = 0;

	virtual void makeDrink()
	{
		Boil();
		Brew();
		PourInCup();
		PutSomething();

	}
};

class Coffee : public AbstractDrinking
{
	virtual void Boil()
	{
		cout << "煮水" << endl;
	}

	virtual void Brew()
	{
		cout << "冲泡咖啡" << endl;
	}

	virtual void PourInCup()
	{
		cout << "倒入杯中" << endl;
	}

	virtual void PutSomething()
	{
		cout << "加糖和牛奶" << endl;
	}
};

class Tea : public AbstractDrinking
{
	virtual void Boil()
	{
		cout << "煮水" << endl;
	}

	virtual void Brew()
	{
		cout << "泡茶" << endl;
	}

	virtual void PourInCup()
	{
		cout << "倒入杯中" << endl;
	}

	virtual void PutSomething()
	{
		cout << "加枸杞" << endl;
	}
};

void doWork(AbstractDrinking* abs)
{
	abs->makeDrink();
	delete abs;
}

void test01()
{
	doWork(new Coffee);
	doWork(new Tea);
}

int main()
{
	test01();
	return 0;
}




//虚析构和纯虚析构(子类有堆数据时，在父类使用)
//可以解决父类指针释放子类对象，都需要有具体的函数实现
//有纯虚析构的类属于抽象类，无法实例化对象，一般用在父类
/*
语法：
虚析构: virtual ~类名(){}
纯虚析构: virtual ~类名() = 0;
*/

class Animal
{
public:
	Animal()
	{
		cout << "Animal构造函数" << endl;
	}

	virtual void speak() = 0;

	//虚析构
	//virtual ~Animal()
	//{
	//	cout << "Aniaml虚析构函数" << endl;
	//}

	//纯虚析构
	virtual ~Animal() = 0;	//必须要有具体函数实现，在类外实现
};

//纯虚析构的具体实现
Animal::~Animal()
{
	cout << "Aniaml纯虚析构函数" << endl;
}

class Cat : public Animal
{
public:
	Cat(string name)
	{
		cout << "Cat构造函数" << endl;
		m_Name = new string(name);
	}

	virtual void speak()
	{
		cout << *m_Name << ": " << "喵喵喵" << endl;
	}

	string* m_Name = NULL;

	~Cat()
	{
		if (m_Name != NULL)
		{
			cout << "Cat析构函数调用" << endl;
			delete m_Name;
			m_Name = NULL;
		}
	}
};

void test01()
{
	Animal* animal = new Cat("Tom");
	animal->speak();	
	//父类指针指向子类对象，父类指针析构时，不会调用子类析构函数
	//导致子类堆区属性泄露
	//解决办法：将父类析构函数改为虚析构
	delete animal;

}

int main()
{
	test01();
	return 0;
}
//如果子类中没有堆区数据，可以不写成虚析构或者纯虚析构
//虚析构用来解决通过父类指针释放子类对象




//多态案例三——电脑组装
//CPU(用于计算)， 显卡(用于显示)， 内存条(用于内存)
class CPU
{
public:
	virtual void calculate() = 0;

};

class VideoCard
{
public:
	virtual void display() = 0;

};

class Memory
{
public:
	virtual void storage() = 0;

};

class Computer
{
private:
	CPU* m_cpu;

	VideoCard* m_vd;

	Memory* m_mem;

public:
	Computer(CPU* cpu, VideoCard* vd, Memory* mem)
	{
		m_cpu = cpu;
		m_vd = vd;
		m_mem = mem;
	}

	void DoWork()
	{
		m_cpu->calculate();

		m_vd->display();

		m_mem->storage();
	}

	~Computer()
	{
		if (m_cpu != NULL)
		{
			delete m_cpu;
			m_cpu = NULL;
		}

		if (m_vd != NULL)
		{
			delete m_vd;
			m_vd = NULL;
		}

		if (m_mem != NULL)
		{
			delete m_mem;
			m_mem = NULL;
		}
	}
};

class Inter_CPU : public CPU
{
public:
	virtual void calculate()
	{
		cout << "Inter_CPU_calculate()" << endl;
	}
};

class Inter_VideoCard : public VideoCard
{
public:
	virtual void display()
	{
		cout << "Inter_CPU_display()" << endl;
	}
};

class Inter_Memory : public Memory
{
public:
	virtual void storage()
	{
		cout << "Inter_CPU_storage()" << endl;
	}
};

class Lenovo_CPU : public CPU
{
public:
	virtual void calculate()
	{
		cout << "Lenovo_CPU_calculate()" << endl;
	}
};

class Lenovo_VideoCard : public VideoCard
{
public:
	virtual void display()
	{
		cout << "Lenovo_CPU_display()" << endl;
	}
};

class Lenovo_Memory : public Memory
{
public:
	virtual void storage()
	{
		cout << "Lenovo_CPU_storage()" << endl;
	}
};

void test01()
{
	cout << "第一台电脑: " << endl;
	CPU* Intercpu = new Inter_CPU;
	VideoCard* Intervd = new Inter_VideoCard;
	Memory* Intermem = new Inter_Memory;

	Computer* computer1 = new Computer(Intercpu, Intervd, Intermem);
	computer1->DoWork();
	delete computer1;

	cout << "--------------------------------------------" << endl;
	cout << "第二台电脑: " << endl;
	Computer computer2(new Inter_CPU, new Lenovo_VideoCard, new Lenovo_Memory);
	computer2.DoWork();
}

int main()
{
	test01();
	return 0;
}
















































